﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Elderos.Highlight.Search;

namespace Elderos.Highlight
{
    internal class PooledAmbiguityResolver : IAmbiguityResolver
    {
        public Func<IAmbiguityResolver> AmbiguityResolverFabric { get; set; }
        public int MinPoolSize { get; private set; }
        public int MaxPoolSize { get; private set; }

        private int _poolSize;
        private object _poolLocker = new object();
        private readonly ConcurrentBag<IAmbiguityResolver> _pool = new ConcurrentBag<IAmbiguityResolver>();

        public PooledAmbiguityResolver(Func<IAmbiguityResolver> ambiguityResolverFabric, 
            int minPoolSize = 20, int maxPoolSize = 100)
        {
            AmbiguityResolverFabric = ambiguityResolverFabric;
            MinPoolSize = minPoolSize;
            MaxPoolSize = maxPoolSize;
            for (int i = 0; i < minPoolSize; i++)
            {
                _pool.Add(ambiguityResolverFabric());
            }
            _poolSize = _pool.Count;
        }


        public void Process(IEnumerable<Position> positions)
        {
            while (true)
            {
                IAmbiguityResolver resolver;
                if (_pool.TryTake(out resolver))
                {
                    try
                    {
                        resolver.Process(positions);
                        return;
                    }
                    finally
                    {
                        _pool.Add(resolver);
                    }
                }
                if (_poolSize < MaxPoolSize)
                {
                    lock (_poolLocker)
                        if (_poolSize < MaxPoolSize)
                        {
                            _pool.Add(AmbiguityResolverFabric());
                            _poolSize++;
                        }
                }
                Thread.Yield();
            }
        }

        public IAmbiguityResolver Clone()
        {
            return new PooledAmbiguityResolver(AmbiguityResolverFabric, MinPoolSize, MaxPoolSize);
        }
    }
}
